package com.ld.config;

import com.ld.service.impl.MyUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	@Autowired
	private MyUserDetailService userDetailsService;
	@Autowired
	private DataSource dataSource;
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//1. 自定义表单认证
		http.formLogin()
			//2. 定义登录页面
			.loginPage("/login.html")
			//3. 定义登录处理页面
			.loginProcessingUrl("/login")
			//4. 登录成功后的跳转页面
			.successForwardUrl("/user/welcome")
			//5. 所有上面的与登录相关的请求页面或路径全部放行
			.permitAll()
			.and()

			//6. 其它的请求必须要认证才能访问
			.authorizeRequests()
			// .antMatchers("/webjars/**").permitAll()

			// 6.1 代表有指定的权限就允许访问指定的路径
			// .antMatchers("/user/findAll").hasAuthority("user")
			// 6.2 当前登录的主体（用户）有user或admin其中的一种权限都可以访问指定页面
			// .antMatchers("/user/findAll").hasAnyAuthority("userxx","admin")
			// 6.3 如果有角色ROLE_user，就可以访问指定的路径
			// .antMatchers("/user/findAll").hasRole("user")
			// 6.4 如果有指定角色列表（userxx,admin）中的一种，就可以访问
			 // .antMatchers("/user/findAll").hasAnyRole("userxx","admin")
			.anyRequest()           // 请它请求
			.authenticated()	    // 都要经过认证才能访问
			.and()

			//7. 对异常的处理
			.exceptionHandling().accessDeniedPage("/unauth.html")
			.and()

			//8. 添加remberMe功能
			.rememberMe()
			.tokenValiditySeconds(100)              // 设置过期时间，以s为单位
			.tokenRepository(tokenRepository())     // 设置数据源
			.userDetailsService(userDetailsService) // 设置对应的userDetailService
			.and()
			// 9. 对csrf禁用
			.csrf().disable();

	}


	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().mvcMatchers("/webjars/**");
	}
	// remember的数据源相关配置
	@Bean
	public PersistentTokenRepository tokenRepository(){
		JdbcTokenRepositoryImpl persistentTokenRepository = new JdbcTokenRepositoryImpl();
		persistentTokenRepository.setDataSource(dataSource);            // 设置数据源
		persistentTokenRepository.setCreateTableOnStartup(true);        // 启动时自动创建表
		return persistentTokenRepository;
	}
	@Bean
	public BCryptPasswordEncoder passwordEncoder(){
		return new BCryptPasswordEncoder();
	}
}
